var win32 = require( './build/Release/win32' );

//通用函数
var empty = function( ){

};
var loop = function( total, single ){
	var i;
	for(i = 0; i<total; i++){
		single( i );
	}
};
var foreach = function( li, single ){
	var p = null;
	for(p in li){
		single( li[p] );
	}
};
var loop_break = function( total, single ){
	var i;
	for(i = 0; i<total; i++){
		if(!single( i )){
			break;
		}
	}
};
var foreach_break = function( li, single ){
	var p;
	for(p in li){
		if(!single( li[p] )){
			break;
		}
	}
};
var reverse = function( li ){
	var rst = [ ];
	loop( li.length, function( i ){
		rst.push( li[li.length-i-1] );
	} );
	return rst;
};

//控件列表
function wslist( less, onInsert, onRemove ){
	var head = null;
	var tail = null;
	//插入辅助函数
	function insertFirst( node ){
		node.prev = null;
		node.next = null;
		head = node;
		tail = node;
		onInsert( node.e, null, null );
	}
	function insertHead( node ){
		node.prev = null;
		node.next = head;
		head.prev = node;
		head = node;
		onInsert( node.e, null, node.next.e );
	}
	function insertTail( node ){
		node.prev = tail;
		node.next = null;
		tail.next = node;
		tail = node;
		onInsert( node.e, node.prev.e, null );
	}
	function insert( node, before, after ){
		node.prev = before;
		node.next = after;
		before.next = node;
		after.prev = node;
		onInsert( node.e, node.prev.e, node.next.e );
	}
	//移除辅助函数
	function removeLast( ){
		onRemove( head.e, null, null );
		head = null;
		tail = null;
	}
	function removeHead( ){
		onRemove( head.e, null, head.next.e );
		head = head.next;
		head.prev = null;
	}
	function removeTail( ){
		onRemove( tail.e, tail.prev.e, null );
		tail = tail.prev;
		tail.next = null;
	}
	function remove( node ){
		onRemove( node.e, node.prev.e, node.next.e );
		node.prev.next = node.next;
		node.next.prev = node.prev;
	}

	return {
		insert: function( e ){
			var present = {
				e: e,
				prev: null,
				next: null
			};
			//唯一
			if(tail==null){
				insertFirst( present );
			}
			else{
				//向前寻找最近一个不大于他的
				var check = tail;
				while(check!=null){
					if(less( present.e, check.e )){
						check = check.prev;
					}
					else{
						break;
					}
				}
				//头
				if(check==null){
					insertHead( present );
				}
				else{
					//尾
					if(check.next==null){
						insertTail( present );
					}
					//中间
					else{
						insert( present, check, check.next );
					}
				}
			}
			return {
				remove: function( ){
					if(present.prev==null){
						//唯一
						if(present.next==null){
							removeLast( );
						}
						//头
						else{
							removeHead( );
						}
					}
					else{
						//尾
						if(present.next==null){
							removeTail( );
						}
						//中间
						else{
							remove( present );
						}
					}
					present = null;
				}
			};
		},
		foreach: function( op ){
			var present = head;
			while(present!=null){
				op( present.e );
				present = present.next;
			}
		}
	};
}

//属性读写
function Attribute( init, setter, skipInitSetter ){
	setter = setter||function( nv ){
		return nv;
	};
	var v;
	if(skipInitSetter){
		v = init;
	}
	else{
		v = setter( init );
	}
	return function( nv ){
		if(nv===undefined){
			return v;
		}
		else{
			v = setter( nv );
		}
	}
}

//颜色
function rgb( r, g, b ){
	return (r&0x000000FF)|((g&0x000000FF)<<8)|((b&0x000000FF)<<16);
}

//程序装载
function onLoad( handler ){

	win32.setup( );

	handler( );

	win32.run( );
}

//位置属性
function Positions( args ){
	return {
		left: Attribute( args.left==undefined? 0 : args.left ),
		top: Attribute( args.top==undefined? 0 : args.top ),
		width: Attribute( args.width==undefined? 0 : args.width ),
		height: Attribute( args.height==undefined? 0 : args.height ),
		z: Attribute( args.z==undefined? 0 : args.z )
	};
}

//比较Z-Index
function zless( l, r ){
	return l.z( )<r.z( );
}

//全局列表
var wsBodys = wslist( zless, empty, empty );

//全局窗口
function Body( args ){
	//区域
	function Area( args, title, parent, ws ){
		//属性
		var attrs = Positions( args );
		//新建
		var hwnd = win32.createWindow( title, attrs.left( ), attrs.top( ), attrs.width( ), attrs.height( ), parent );
		//元素队列
		var wsEls = wslist( zless, empty, empty );
		//区域队列
		var wsAreas = wslist( zless, empty, empty );
		//重绘
		win32.onEvent( hwnd, 1, function( hdc ){
			wsEls.foreach( function( e ){
				e.paint( hdc );
			} );
		} );
		//注册自己
		var ah = ws.insert( {
			hwnd: hwnd,
			z: attrs.z
		} );
		//指令集
		var rst = {
			//生成子区域
			area: function( args ){
				return Area( args, "", hwnd, wsAreas );
			},
			//生成元素
			//Ctor需返回remove,paint
			element: function( Ctor, args ){
				//字段
				var fields = { };
				//指令
				var insts = Positions( args );
				//构造
				var util = Ctor( args, insts, fields );
				//事件回调
				var handlers = {
					onDestroy: null
				};
				//事件
				insts.onDestroy = function( handler ){
					handlers.onDestroy = function( ){
						handler( );
						util.remove( );
					}
				};
				//注册自己
				var eh = wsEls.insert( {
					remove: handlers.onDestroy,
					paint: util.paint,
					z: insts.z
				} );
				//移除指令
				insts.remove = function( ){
					handlers.onDestroy( );
					eh.remove( );
				};
				return insts;
			},
			//移除
			remove: function( ){
				win32.destroyWindow( hwnd );
			},
			//事件
			onDestroy: function( handler ){
				win32.onEvent( hwnd, 0, function( ){
					handler( );
					ah.remove( );
					wsEls.foreach( function( e ){
						e.remove( );
					} );
				} );
			}
		};
		for(a in attrs){
			rst[a] = attrs[a];
		}
		return rst;
	}

	//Body带标Win32题栏
	var title = args.title==undefined? "" : args.title;
	var rst = Area( args, title, 0, wsBodys );
	rst.title = Attribute( title );
	return rst;
}

function Rect( args, insts, fields ){
	insts.hbr = Attribute( args.hbr==undefined? 0 : args.hbr );
	return {
		remove: empty,
		paint: function( hdc ){
			win32.drawRect( hdc, insts.left( ), insts.top( ), insts.width( ), insts.height( ), insts.hbr( ) );
		}
	};
}

function Image( args, insts, fields ){
	insts.hbmp = Attribute( args.hbmp==undefined? 0 : args.hbmp, function( hbmp ){
		var wh;
		if(hbmp!=0){
			wh = win32.getImageInfo( hbmp );
			fields.width = wh.width;
			fields.height = wh.height;
			return hbmp;
		}
		else{
			return 0;
		}
	} );
	insts.mode = Attribute( args.mode==undefined? 0 : args.mode );
	return {
		remove: empty,
		paint: function( hdc ){
			//平铺用
			var px;
			var py;
			//按模式画
			switch(insts.mode( )){
			//原图
			case 0:
				win32.drawImage( hdc, insts.left( ), insts.top( ), fields.width, fields.height, insts.hbmp( ), 0, 0, fields.width, fields.height );
				break;
			//拉伸
			case 1:
				win32.drawImage( hdc, insts.left( ), insts.top( ), insts.width( ), insts.height( ), insts.hbmp( ), 0, 0, fields.width, fields.height );
				break;
			//平铺
			case 2:
				px = 0;
				while(px<insts.width( )-fields.width){
					py = 0;
					while(py<insts.height( )-fields.height){
						win32.drawImage( hdc, insts.left( )+px, insts.top( )+py, fields.width, fields.height, insts.hbmp( ), 0, 0, fields.width, fields.height );
						py += fields.height;
					}
					win32.drawImage( hdc, insts.left( )+px, insts.top( )+py, fields.width, insts.height( )-py, insts.hbmp( ), 0, 0, fields.width, insts.height( )-py );
					px += fields.width;
				}
				py = 0;
				while(py<insts.height( )-fields.height){
					win32.drawImage( hdc, insts.left( )+px, insts.top( )+py, insts.width( )-px, fields.height, insts.hbmp( ), 0, 0, insts.width( )-px, fields.height );
					py += fields.height;
				}
				win32.drawImage( hdc, insts.left( )+px, insts.top( )+py, insts.width( )-px, insts.height( )-py, insts.hbmp( ), 0, 0, insts.width( )-px, insts.height( )-py );
				break;
			}
		}
	};
};

function Text( args, insts, fields ){
	insts.text = Attribute( args.text==undefined? "" : args.text );
	insts.hfont = Attribute( args.hfont==undefined? 0 : args.hfont );
	insts.color = Attribute( args.color==undefined? rgb( 0, 0, 0 ) : args.color );
	return {
		remove: empty,
		paint: function( hdc ){
			win32.drawText( hdc, insts.left( ), insts.top( ), insts.width( ), insts.height( ), insts.hfont( ), insts.color( ), insts.text( ) );
		}
	};
}

exports.onLoad = onLoad;

exports.Body = Body;

exports.Image = Image;
exports.Rect = Rect;
exports.Text = Text;

exports.createBrush = win32.createBrush;
exports.createBitmap = win32.createBitmap;
exports.createFont = win32.createFont;

exports.getImageInfo = win32.getImageInfo;
exports.getTextInfo = win32.getTextInfo;

exports.alert = win32.alert;
exports.exit = win32.exit;

exports.rgb = rgb;
